package com.example.project.utils;

import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.seg.common.Term;
import com.hankcs.hanlp.tokenizer.StandardTokenizer;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 基于HanLP的自然语言处理工具类
 */
public class HanLPUtil {
    
    /**
     * 使用HanLP提取关键词（改进版）
     */
    public static List<String> extractKeywords(String text, int maxKeywords) {
        if (text == null || text.trim().isEmpty()) {
            return new ArrayList<>();
        }
        
        // 使用HanLP的关键词提取功能
        List<String> keywords = HanLP.extractKeyword(text, maxKeywords);
        
        return keywords;
    }
    
    /**
     * 使用HanLP进行分词和词性标注
     */
    public static List<Term> segmentText(String text) {
        if (text == null || text.trim().isEmpty()) {
            return new ArrayList<>();
        }
        
        return StandardTokenizer.segment(text);
    }
    
    /**
     * 提取名词和动词作为关键词（更适合需求分析）
     */
    public static List<String> extractKeywordsByPOS(String text, int maxKeywords) {
        if (text == null || text.trim().isEmpty()) {
            return new ArrayList<>();
        }
        
        List<Term> terms = segmentText(text);
        
        // 筛选名词和动词
        List<String> keywords = terms.stream()
                .filter(term -> {
                    String pos = term.nature.toString();
                    // 名词：n, nr, ns, nt, nz, nl, ng
                    // 动词：v, vd, vn, vf, vx, vi, vl, vg
                    return pos.startsWith("n") || pos.startsWith("v");
                })
                .map(term -> term.word)
                .distinct()
                .limit(maxKeywords)
                .collect(Collectors.toList());
        
        return keywords;
    }
    
    /**
     * 提取技术相关关键词（专门针对需求文档）
     */
    public static List<String> extractTechnicalKeywords(String text, int maxKeywords) {
        if (text == null || text.trim().isEmpty()) {
            return new ArrayList<>();
        }
        
        List<Term> terms = segmentText(text);
        
        // 技术相关的词性
        Set<String> techPos = new HashSet<>(Arrays.asList(
            "n", "v", "vn", "a", "ad", "b" // 名词、动词、动名词、形容词、副形词、区别词
        ));
        
        // 常见技术词汇（可根据项目特点扩展）
        Set<String> techWords = new HashSet<>(Arrays.asList(
            "bug", "修复", "功能", "需求", "测试", "开发", "代码", "接口", "数据库",
            "性能", "优化", "安全", "部署", "配置", "日志", "监控", "异常", "错误",
            "用户", "权限", "登录", "注册", "支付", "订单", "库存", "物流", "报表",
            "API", "SDK", "框架", "组件", "模块", "系统", "平台", "服务", "应用"
        ));
        
        List<String> keywords = terms.stream()
                .filter(term -> {
                    String pos = term.nature.toString();
                    // 筛选技术相关的词性
                    boolean isTechPos = techPos.stream().anyMatch(pos::startsWith);
                    // 或者包含在技术词汇库中
                    boolean isTechWord = techWords.contains(term.word);
                    
                    return isTechPos || isTechWord;
                })
                .map(term -> term.word)
                .distinct()
                .limit(maxKeywords)
                .collect(Collectors.toList());
        
        return keywords;
    }
    
    /**
     * 计算文本相似度（基于HanLP的语义向量）
     */
    public static double calculateSimilarity(String text1, String text2) {
        if (text1 == null || text2 == null) {
            return 0.0;
        }
        
        if (text1.equals(text2)) {
            return 1.0;
        }
        
        // 使用HanLP的文本相似度计算
        // 方法1：基于关键词的Jaccard相似度
        return calculateJaccardSimilarity(text1, text2);
    }
    
    /**
     * 基于Jaccard相似度的文本相似度计算
     */
    private static double calculateJaccardSimilarity(String text1, String text2) {
        if (text1 == null || text2 == null) {
            return 0.0;
        }
        
        // 提取关键词
        List<String> keywords1 = extractTechnicalKeywords(text1, 20);
        List<String> keywords2 = extractTechnicalKeywords(text2, 20);
        
        if (keywords1.isEmpty() && keywords2.isEmpty()) {
            return 1.0;
        }
        
        if (keywords1.isEmpty() || keywords2.isEmpty()) {
            return 0.0;
        }
        
        Set<String> set1 = new HashSet<>(keywords1);
        Set<String> set2 = new HashSet<>(keywords2);
        
        // 计算Jaccard相似度
        Set<String> intersection = new HashSet<>(set1);
        intersection.retainAll(set2);
        
        Set<String> union = new HashSet<>(set1);
        union.addAll(set2);
        
        return (double) intersection.size() / union.size();
    }
    
    /**
     * 提取文本摘要
     */
    public static String extractSummary(String text, int maxSentences) {
        if (text == null || text.trim().isEmpty()) {
            return "";
        }
        
        List<String> sentences = HanLP.extractSummary(text, maxSentences);
        return String.join("。", sentences) + "。";
    }
    
    /**
     * 提取短语（更适合需求分析）
     */
    public static List<String> extractPhrases(String text, int maxPhrases) {
        if (text == null || text.trim().isEmpty()) {
            return new ArrayList<>();
        }
        
        List<String> phrases = HanLP.extractPhrase(text, maxPhrases);
        return phrases;
    }
    
    /**
     * 需求分类（基于关键词匹配）
     */
    public static String classifyRequirement(String text) {
        if (text == null || text.trim().isEmpty()) {
            return "其他";
        }
        
        List<String> keywords = extractTechnicalKeywords(text, 10);
        
        // 需求分类规则（可根据项目特点调整）
        Map<String, Set<String>> categoryKeywords = new HashMap<>();
        categoryKeywords.put("功能需求", new HashSet<>(Arrays.asList(
            "功能", "需求", "用户", "界面", "操作", "流程", "业务", "逻辑"
        )));
        categoryKeywords.put("技术需求", new HashSet<>(Arrays.asList(
            "技术", "架构", "性能", "安全", "数据库", "接口", "API", "部署"
        )));
        categoryKeywords.put("缺陷修复", new HashSet<>(Arrays.asList(
            "bug", "修复", "错误", "异常", "问题", "故障", "解决"
        )));
        categoryKeywords.put("优化改进", new HashSet<>(Arrays.asList(
            "优化", "改进", "提升", "增强", "完善", "重构"
        )));
        
        String bestCategory = "其他";
        int bestMatchCount = 0;
        
        for (Map.Entry<String, Set<String>> entry : categoryKeywords.entrySet()) {
            String category = entry.getKey();
            Set<String> categoryWords = entry.getValue();
            
            long matchCount = keywords.stream()
                    .filter(categoryWords::contains)
                    .count();
            
            if (matchCount > bestMatchCount) {
                bestMatchCount = (int) matchCount;
                bestCategory = category;
            }
        }
        
        return bestMatchCount > 0 ? bestCategory : "其他";
    }
    
    /**
     * 提取需求优先级关键词
     */
    public static String extractPriority(String text) {
        if (text == null || text.trim().isEmpty()) {
            return "普通";
        }
        
        List<String> keywords = extractKeywords(text, 10);
        
        // 优先级关键词匹配
        Map<String, Set<String>> priorityKeywords = new HashMap<>();
        priorityKeywords.put("紧急", new HashSet<>(Arrays.asList(
            "紧急", "立刻", "马上", "立即", "重要", "关键", "阻塞", "故障"
        )));
        priorityKeywords.put("高", new HashSet<>(Arrays.asList(
            "高", "重要", "核心", "主要", "必要", "必须"
        )));
        priorityKeywords.put("普通", new HashSet<>(Arrays.asList(
            "普通", "一般", "常规", "标准", "正常"
        )));
        priorityKeywords.put("低", new HashSet<>(Arrays.asList(
            "低", "次要", "可选", "优化", "改进"
        )));
        
        for (Map.Entry<String, Set<String>> entry : priorityKeywords.entrySet()) {
            String priority = entry.getKey();
            Set<String> priorityWords = entry.getValue();
            
            boolean hasMatch = keywords.stream()
                    .anyMatch(priorityWords::contains);
            
            if (hasMatch) {
                return priority;
            }
        }
        
        return "普通";
    }
    
    /**
     * 计算需求相似度（综合多种特征）
     */
    public static double calculateRequirementSimilarity(String title1, String desc1, 
                                                       String title2, String desc2) {
        if (title1 == null || title2 == null) {
            return 0.0;
        }
        
        // 标题相似度（权重最高）
        double titleSimilarity = calculateSimilarity(title1, title2);
        
        // 描述相似度
        double descSimilarity = 0.0;
        if (desc1 != null && desc2 != null) {
            descSimilarity = calculateSimilarity(desc1, desc2);
        }
        
        // 关键词相似度
        double keywordSimilarity = calculateKeywordSimilarity(title1 + " " + desc1, 
                                                              title2 + " " + desc2);
        
        // 综合相似度计算（可根据需求调整权重）
        return titleSimilarity * 0.5 + descSimilarity * 0.3 + keywordSimilarity * 0.2;
    }
    
    /**
     * 基于关键词的相似度计算
     */
    private static double calculateKeywordSimilarity(String text1, String text2) {
        List<String> keywords1 = extractTechnicalKeywords(text1, 15);
        List<String> keywords2 = extractTechnicalKeywords(text2, 15);
        
        if (keywords1.isEmpty() && keywords2.isEmpty()) {
            return 1.0;
        }
        
        if (keywords1.isEmpty() || keywords2.isEmpty()) {
            return 0.0;
        }
        
        Set<String> set1 = new HashSet<>(keywords1);
        Set<String> set2 = new HashSet<>(keywords2);
        
        Set<String> intersection = new HashSet<>(set1);
        intersection.retainAll(set2);
        
        Set<String> union = new HashSet<>(set1);
        union.addAll(set2);
        
        return (double) intersection.size() / union.size();
    }
}